package by.epam.trenings.vkphotorest.imageLoader;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;

import by.epam.trenings.vkphotorest.http.HttpManager;
import by.epam.trenings.vkphotorest.utils.context.ContextHolder;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Point;
import android.os.AsyncTask;
import android.os.Build;
import android.view.Display;
import android.view.WindowManager;
import android.widget.BaseAdapter;
import android.widget.ImageView;

public class testLoader {

	private Map<ImageView, String> mImageViews;

	private BitmapLruCache<String> mCache;

	private List<Callback> mQueue;

	public interface Callback {

		String getUrl();

		void success(Bitmap bm);

		void onError(Exception e);

		ImageView getImageVIew();
	}

	public testLoader() {
		mCache = new BitmapLruCache<String>(getCacheMemory());
		mQueue = Collections.synchronizedList(new ArrayList<Callback>());
		mImageViews = Collections
				.synchronizedMap(new WeakHashMap<ImageView, String>());
	}

	/**
	 * Get max capacity of LRU cache it gives 1/4 of the maximum available
	 * memory
	 */
	private int getCacheMemory() {
		int maxCachMemory;
		// imageCacheLimit measured in bits 2097152 equals 2 Mb
		int imageCacheLimit = 2097152;
		int size = (int) (Runtime.getRuntime().maxMemory() / 4);
		if (size > imageCacheLimit) {
			maxCachMemory = size;
		} else {
			maxCachMemory = imageCacheLimit;
		}
		return maxCachMemory;
	}

	/** Check if ImageView reused */
	private Boolean isImageViewReused(ImageView imageView, String url) {
		String value = mImageViews.get(imageView);
		if (value == null || !value.equals(url)) {
			return true;
		}
		return false;
	}

	public void bind(final BaseAdapter adapter, final ImageView imageView,
			final String url) {
		Bitmap bitmap = null;
		if (mCache.containsKey(url)) {
			bitmap = mCache.get(url);
		}

		if (bitmap != null) {
			imageView.setImageBitmap(bitmap);
			return;
		} else {
			mQueue.add(0, new Callback() {

				@Override
				public void success(Bitmap bm) {
					adapter.notifyDataSetChanged();
				}

				@Override
				public String getUrl() {
					return url;
				}

				@Override
				public void onError(Exception e) {
					// TODO Auto-generated method stub

				}

				@Override
				public ImageView getImageVIew() {
					// TODO Auto-generated method stub
					return null;
				}
			});
		}
		proceed();
	}

	public void bind(final ImageView imageView, final String url) {
		Bitmap bitmap = mCache.get(url);
		if (bitmap != null) {
			imageView.setImageBitmap(bitmap);
			return;
		} else {
			mImageViews.put(imageView, url);
			mQueue.add(0, new Callback() {

				@Override
				public void success(Bitmap bm) {
					if (!isImageViewReused(imageView, url)) {
						imageView.setImageBitmap(bm);
						mImageViews.remove(url);
					}
				}

				@Override
				public String getUrl() {
					return url;
				}

				@Override
				public void onError(Exception e) {
					// TODO Auto-generated method stub
					// smth
					// imageView.setBackgroundResource(android.R.drawable.ic_error);
				}

				@Override
				public ImageView getImageVIew() {
					return imageView;
				}

			});
		}
		proceed();
	}

	private void proceed() {
		if (mQueue.isEmpty()) {
			return;
		}
		final Callback callback = mQueue.remove(0);
		new AsyncTask<Callback, Void, Object>() {

			@Override
			protected Object doInBackground(Callback... params) {
				try {
					String url = params[0].getUrl();
					Bitmap bitmap = null;
					bitmap = mCache.get(url);
					if (bitmap != null) {
						return bitmap;
					} else {
						if (!isImageViewReused(params[0].getImageVIew(), url)) {
							bitmap = sizeProcessor(HttpManager.getInstance()
									.loadAsBitmap(url));
						}
					}
					return bitmap;
				} catch (Exception e) {
					return e;
				}
			}

			@Override
			protected void onPostExecute(Object result) {
				super.onPostExecute(result);
				if (result instanceof Bitmap) {
					Bitmap bitmap = (Bitmap) result;
					mCache.put(callback.getUrl(), bitmap);
					callback.success(bitmap);
					// TODO start thread to cache
				} else if (result != null) {
					callback.onError((Exception) result);
				}
			}

		}.execute(callback);
		// TODO or executeOnExecutor
	}

	/** Resize bitmap to size of displayy */
	@SuppressLint("NewApi")
	private Bitmap sizeProcessor(Bitmap bitmap) {

		int origWidth = bitmap.getWidth();
		int origHeight = bitmap.getHeight();

		WindowManager window = (WindowManager) ContextHolder.getInstance()
				.getContext().getSystemService(Context.WINDOW_SERVICE);
		Display display = window.getDefaultDisplay();
		int displayWidth;
		int displayHeight;
		if (Build.VERSION.SDK_INT > 12) {
			Point size = new Point();
			display.getSize(size);
			displayWidth = size.x;
			displayHeight = size.y;
		} else {
			displayWidth = display.getWidth();
			displayHeight = display.getHeight();
		}
		if (origWidth > displayWidth || origHeight > displayHeight) {

			while (origWidth > displayWidth || origHeight > displayHeight) {
				origWidth /= 2;
				origHeight /= 2;
			}

			bitmap = Bitmap.createScaledBitmap(bitmap, origWidth, origHeight,
					false);
		}
		return bitmap;
	}

}
